home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlib25 / mntlib25.zoo / findfile.c < prev   
C/C++ Source or Header  |  1992-09-05  |  3KB  |  108 lines

  1. /* findfile: given a base filename, a list of directories, and a list
  2.    of possible extensions to the filename, attempts to find a file.
  3.    Useful for doing, e.g. spawnvp. Note that the current directory
  4.    is always searched first! If the filename already contains a
  5.    path specification (or extension) then the given path list
  6.    (or extension list) is ignored.
  7.    Returns the name by which the file was found, or NULL.
  8.  
  9.    Written by Eric R. Smith and placed in the public domain.
  10. */
  11.  
  12. #include <compiler.h>
  13. #include <limits.h>    /* needed for PATH_MAX */
  14. #include <stddef.h>
  15. #include <types.h>
  16. #include <stat.h>
  17. #include <string.h>
  18.  
  19. /* characters used to separate components in a path list */
  20. #define PATHSEP1        ':'
  21. #define PATHSEP2        ','
  22.  
  23. /* characters used to separate directory names in a file */
  24. #define DIRSEP1         '\\'    /* native OS directory separator */
  25. #define DIRSEP2         '/'     /* for emulating another OS */
  26.  
  27. static char *nullext[] = { NULL };
  28.  
  29. static int EXISTS __PROTO((char *));
  30. char *findfile __PROTO((char *fname, char *fpath, char **fext));
  31.  
  32. static int
  33. EXISTS(name)
  34.     char *name;
  35. {
  36.     struct stat dummy;
  37.  
  38.     if (stat(name, &dummy) != 0)
  39.         return 0;
  40.     if ( (dummy.st_mode & S_IFMT) != S_IFREG )
  41.         return 0;
  42.     return 1;
  43. }
  44.  
  45. char *
  46. findfile(fname, fpath, fext)
  47.         char *fname, *fpath, **fext;
  48. {
  49.         static char try[PATH_MAX];
  50.         char *s, *t, *extplace, **nextext, c;
  51.         int  hasext = 0, haspath = 0;
  52.  
  53.     if (!fname || !*fname)
  54.         return NULL;
  55.  
  56.         s = try; t = fname;
  57.  
  58. /* copy the file in, checking to see if a path and/or extension are already
  59.    given */
  60.  
  61.         while ( (c = *t++) != 0 ) {
  62.                 if (c == DIRSEP1 || c == DIRSEP2) {
  63.                         haspath = 1; hasext = 0;
  64.                 }
  65.                 else if (c == '.')
  66.                         hasext = 1;
  67.                 *s++ = c;
  68.         }
  69.         extplace = s;
  70.         *s++ = 0;
  71.  
  72.         if (haspath || !fpath)
  73.                 fpath = "";
  74.         if (hasext || !fext)
  75.                 fext = nullext;
  76.  
  77.         for(;;) {               /* loop on path elements */
  78.                 nextext = fext;
  79.         if (!hasext) {
  80.             extplace[0] = 0;
  81.             extplace[1] = 0;
  82.         }
  83.  
  84.         if (EXISTS(try))
  85.             return try;
  86.         extplace[0] = '.';
  87.                 while(*nextext) {       /* loop on extensions */
  88.                         (void)strcpy(&extplace[1], *nextext++);
  89.                         if (EXISTS(try))
  90.                                 return try;
  91.                 }
  92.                 if (!*fpath) break;  /* no more places to look */
  93.  
  94. /* copy in next element of path list */
  95.                 s = try;
  96.                 while ((c = *fpath) != 0 && c != PATHSEP1 && c != PATHSEP2) {
  97.                         *s++ = c;
  98.                         fpath++;
  99.                 }
  100.                 if (c) fpath++;
  101.                 *s++ = DIRSEP1;
  102.                 t = fname;
  103.                 while ((*s++ = *t++) != 0) ;
  104.                 extplace = --s ;        /* where the extension gets written */
  105.         }
  106.         return NULL;
  107. }
  108.